home *** CD-ROM | disk | FTP | other *** search
- ;*************************************************************************
- ;** mmu.library **
- ;** **
- ;** a system library for arbitration and control of the MC68K MMUs **
- ;** **
- ;** © 1998 THOR-Software, Thomas Richter **
- ;** No commercial use, reassembly, modification without prior, written **
- ;** permission of the authors. **
- ;** Including this library in any commercial software REQUIRES a **
- ;** written permission and the payment of a small fee. **
- ;** **
- ;** This is an internal header file, do not depend on anything here. **
- ;** Use the official include files. **
- ;** Distributed only for the mmu.library development group for private **
- ;** use. **
- ;** **
- ;**---------------------------------------------------------------------**
- ;** Block: 68851 specific routines **
- ;*************************************************************************
-
- ;FOLD Includes
- include mu_lib.i
- include mu_context.i
- include mu_alerts.i
- include mu_descriptor.i
- ;ENDFOLD
- ;FOLD External references
- xref SubSuper
- xref MUAlert
- xref AddTransparentTranslation
- ;ENDFOLD
-
- section main_code,code
-
- machine mc68020
- pmmu
-
- ;FOLD Init851
- ;*************************************************
- ;** Init851 **
- ;** Initialize internal vectors of the library **
- ;** base for the use of the 68851 MMU **
- ;** **
- ;** *a6 = library base **
- ;** returns success/failure in d0 **
- ;*************************************************
- xdef Init851
- Init851:
- lea ReadConfig(pc),a0
- move.l a0,2+mulib_ReadConfig(a6) ;no need to flush the cache, that's done by the library anyways
- lea WriteConfig(pc),a0
- move.l a0,2+mulib_WriteConfig(a6)
- lea SetLibrary(pc),a0
- move.l a0,2+mulib_SetLibrary(a6)
- lea RootStarter(pc),a0
- move.l a0,2+mulib_RootStarter(a6)
- lea ReadDescriptor(pc),a0
- move.l a0,2+mulib_ReadDescriptor(a6)
- lea CmpDescriptor(pc),a0
- move.l a0,2+mulib_CmpDescriptor(a6)
- lea ReadIncrement(pc),a0
- move.l a0,2+mulib_ReadIncrement(a6)
- moveq #1,d0
- rts
- ;ENDFOLD
- ;FOLD ReadConfig
- ;*************************************************
- ;** ReadConfig **
- ;** Read the MMU configuration **
- ;** to *a0 struct MMUConfig **
- ;*************************************************
- ReadConfig:
- pea _ReadConfig(pc)
- bsr SubSuper
- rts
- _ReadConfig:
- pmove tc,mcf_translationctrl(a0) ;read the translation control register
- tst.l mcf_translationctrl(a0) ;get it
- bpl.s .disabled ;if disabled, ignore it
- pmove crp,mcf_userrootpointer(a0)
- and.w #3,2+mcf_userrootpointer(a0) ;avoid trouble and clear unused bits
- btst #1,mcf_translationctrl(a0) ;SRP used?
- beq.s .disabled
- pmove srp,mcf_superrootpointer(a0)
- and.w #3,2+mcf_superrootpointer(a0) ;avoid trouble and clear unused bits
- .disabled:
- rte
- ;ENDFOLD
- ;FOLD WriteConfig
- ;*************************************************
- ;** WriteConfig **
- ;** install the MMU configuration in *a0 **
- ;*************************************************
- WriteConfig:
- pea _WriteConfig(pc)
- bsr SubSuper
- rts
- _WriteConfig:
- ori.w #$0700,sr ;all interrupts off
- ;here: enable it
- clr.l -(a7)
- movec.l cacr,d0
- pmove (a7),tc ;clear translation control
- or.w #$808,d0 ;prepare for flush
- tst.l mcf_translationctrl(a0) ;MMU disabled ?
- bpl.s .disableme
- pmove mcf_userrootpointer(a0),crp
- btst #1,mcf_translationctrl(a0)
- beq.s .nosrp
- pmove mcf_superrootpointer(a0),srp ;write urp,srp
- .nosrp:
- pmove mcf_translationctrl(a0),tc ;translation control
- .disableme:
- movec.l d0,cacr ;flush the cache
- pflusha ;flush address translation cache
- addq.l #4,a7
- rte
- ;ENDFOLD
- ;FOLD SetLibrary
- ;*************************************************
- ;** SetLibrary **
- ;** set the data in the library base from **
- ;** the MMUConfig *a0 **
- ;*************************************************
- SetLibrary:
- move.l mcf_translationctrl(a0),d0 ;get TC
- bpl.s .disabled ;is it enabled ?
- ;here yes: Read the values and life with them
- bfextu d0{12:4},d1
- move.b d1,mulib_InitialShift(a6)
- bfextu d0{16:4},d1
- move.b d1,mulib_LevelABits(a6)
- bfextu d0{20:4},d1
- move.b d1,mulib_LevelBBits(a6)
- bfextu d0{24:4},d1
- move.b d1,mulib_LevelCBits(a6)
- bfextu d0{28:4},d1
- move.b d1,mulib_LevelDBits(a6)
- bfextu d0{8:4},d1
- move.b d1,mulib_PageBits(a6)
- ;now fill in the root pointers in the library base
- bra.s .setmasks
- .disabled:
- ;default: Mimic the '060 page layout
- move.b #12,mulib_PageBits(a6) ;Page size is 4K
- move.b #6,mulib_LevelCBits(a6) ;6 Bits for Level C
- move.b #7,mulib_LevelBBits(a6) ;7 Bits for Level D
- move.b #7,mulib_LevelABits(a6) ;7 Bits for Level A
- clr.b mulib_InitialShift(a6)
- clr.b mulib_LevelDBits(a6) ;no Level D, no Initial Shift
- .setmasks:
- move.l #$0010,d0
- move.l d0,mulib_LevelAAlign(a6)
- move.l d0,mulib_LevelBAlign(a6)
- move.l d0,mulib_LevelCAlign(a6)
- move.l d0,mulib_LevelDAlign(a6)
-
- moveq #0,d0
- move.b mulib_PageBits(a6),d1 ;get the page size
- bset d1,d0
- move.l d0,mulib_PageAlign(a6) ;this is the page size, too
- rts
- ;ENDFOLD
- ;FOLD RootStarter
- ;*************************************************
- ;** RootStarter **
- ;** given the MMU configuration *a1, fill in **
- ;** the location of the root pointer into the **
- ;** abstract descriptor at *a0 **
- ;** return 0 if no avail **
- ;** return -1 if worked **
- ;** return 1 if disabled **
- ;*************************************************
- RootStarter:
- movem.l a2,-(a7)
-
- btst #7,mcf_translationctrl(a1) ;enabled ?
- beq.s .disabled
-
- move.l a0,a2
- lea mcf_userrootpointer(a1),a0
-
- move.l a0,atd_Pointer(a2) ;the pointer is here
- clr.l atd_LowerLimit(a2)
- clr.l atd_UpperLimit(a2) ;just one valid entry here, obviously
-
- move.b #atdt_table,atd_ThisType(a2)
- move.b #atdt_table!atdt_long,atd_NextType(a2) ;the root pointer is always long
-
- bfextu mcf_userrootpointer(a1){30:2},d0 ;get the descriptor type
- btst #1,d0 ;must be short or long. Everything else is not useful
- beq.s .gurume ;if not, return GURU.
-
- btst #0,mcf_translationctrl(a1) ;function code lookup enabled ? (Huh?)
- bne.s .gurume
-
- moveq #-1,d0
- bra.s .exit
-
- .disabled:
- moveq #1,d0
- bra.s .exit
- .gurume:
- pea AN_IllegalMMU
- bsr MUAlert
- moveq #0,d0
- .exit:
- movem.l (a7)+,a2
- rts
- ;ENDFOLD
- ;FOLD ReadDescriptor
- ;*************************************************
- ;** ReadDescriptor **
- ;** read the descriptor pointed to by *a1 **
- ;** fill in the abstract table descriptor *a0 **
- ;** type (of this one) is in d0 **
- ;** level is in d1 **
- ;* (=0 is level A, -1 is root, 4 is page) **
- ;** Context is in *a5 **
- ;*************************************************
- ReadDescriptor:
- movem.l d2-d3,-(a7)
-
- moveq #0,d2 ;no properties
- move.l #$7fff,atd_LowerLimit(a0) ;clear limits
-
- btst #atdf_long,d0 ;long or short ?
- beq.s .nosuper
- btst #0,2(a1) ;supervisor only ?
- beq.s .nosuper
- bset #mapp_supervisoronly,d2
- .nosuper:
- btst #2,3(a1) ;write protected
- beq.s .nowp
- bset #mapp_writeprotected,d2
- .nowp:
- bfextu (a1){30:2},d3 ;read the descriptor type
- beq.s .invalid
- cmp.b #1,d3 ;is early termination?
- beq.s .termination
- cmp.b #2,d3 ;short page ?
- beq.s .isshort
- move.b #atdt_table!atdt_long,atd_NextType(a0) ;next type is long
- bra.s .foundtype
- .isshort:
- move.b #atdt_table,atd_NextType(a0) ;next is short
- .foundtype:
- and.b #atdt_long,d0 ;map out size of this level
- cmp.b #4,d1 ;are we at page level?
- beq.s .indirect ;if so, this is an indirect descriptor
- bgt.s .invalid ;if indirect at higher level, so invalid
- or.b #atdt_table,d0 ;table descriptor
- bra.s .found
- .indirect:
- or.b #atdt_indirect,d0
- .found:
- move.l (a1),d3 ;get page address
- move.b d0,atd_ThisType(a0) ;this type found
- btst #atdf_long,d0 ;is this long ?
- beq.s .short
- move.l 4(a1),d3
- .short:
- and.l ctx_LevelAMask(a5,d1.w*4),d3 ;mask out pointer
- move.l d3,atd_Pointer(a0) ;write pointer
- bra.s .readlimit ;now fill in the limit
-
- .termination:
- move.l (a1),d3 ;read page address
- move.b #atdt_invalid,atd_NextType(a0) ;there is no next type
- btst #6,d3 ;cache inhibit ?
- bne.s .nocache
- bset #mapp_copyback,d2 ;turn on copyback, even though the '020 doesn't support this
- bra.s .gotcache
- .nocache:
- bset #mapp_cacheinhibit,d2
- .gotcache:
- btst #atdf_long,d0 ;is this long ?
- beq.s .shortterm
- move.l 4(a1),d3
- .shortterm:
- and.l ctx_PageMask(a5),d3
- move.b #atdt_page,atd_ThisType(a0) ;This type is invalid
- move.l d3,atd_Pointer(a0) ;this is the pointer
- cmp.b #4,d1 ;are we at page level
- bge.s .exit ;or below? No limit
- .readlimit: ;read limit
- btst #atdf_long,d0 ;long descriptor?
- beq.s .exit ;if not, no limits
- move.w (a1),d0 ;read limit
- bclr #15,d0 ;is this flag set
- bne.s .lowerlimit ;lower or upper limit given?
- move.w d0,atd_UpperLimit(a0) ;if upper, set this
- bra.s .exit
- .lowerlimit:
- move.w d0,atd_LowerLimit(a0)
- bra.s .exit
-
- .invalid:
- clr.l atd_Pointer(a0) ;clear the pointer
- move.b #atdt_invalid,atd_ThisType(a0) ;This type is invalid
- move.b #atdt_invalid,atd_NextType(a0) ;there is no next type
- move.l #(1<<mapp_invalid),d2
- .exit:
- move.l d2,atd_Properties(a0)
-
- movem.l (a7)+,d2-d3
- rts
- ;ENDFOLD
- ;FOLD CmpDescriptor
- ;*************************************************
- ;** CmpDescriptor **
- ;** compare, whether the descriptor *a0 **
- ;** is equal to the descriptor *a1 plus delta **
- ;** in d1. Type is found in d0 **
- ;** advance a1 by one entry, keep a0 **
- ;** returns eq, if identically **
- ;*************************************************
- CmpDescriptor:
-
- bclr #atdf_long,d0 ;long or short ?
- beq.s .short
- cmp.b #atdt_indirect,d0
- bne.s .nolongindirect
- move.l (a1)+,d0 ;long indirect descriptor ?
- move.l (a0),d1
- eor.l d1,d0
- addq.l #4,a1
- and.b #$3,d0 ;type must be equal
- bne.s .exit ;unequal ?
- move.l 4(a0),d1
- move.l -4(a1),d0
- eor.l d0,d1
- and.l #%11111111111111111111111111111100,d1
- bra.s .exit
- .nolongindirect:
- move.l d2,-(a7)
- move.l (a1)+,d0
- move.l (a0),d2
- eor.l d2,d0
- addq.l #4,a1
- move.l (a7)+,d2
- and.l #%11111111111111111111111111100111,d0
- bne.s .exit ;unequal ?
- ;we accept, too, descriptors which
- ;are both invalid but contain different data
- move.l (a0),d0
- and.b #3,d0
- beq.s .exit ;if invalid, don't care about the data
- .cmppage:
- add.l 4(a0),d1
- move.l -4(a1),d0
- eor.l d0,d1
- and.l #%11111111111111111111111111110000,d1
- bra.s .exit
- .short:
- cmp.b #atdt_indirect,d0
- bne.s .noshortindirect
- move.l (a0),d1
- cmp.l (a1)+,d1 ;must be equal bit for bit
- bra.s .exit
- .noshortindirect:
- add.l (a0),d1
- move.l (a1)+,d0
- eor.l d0,d1
- and.l #%11111111111111111111111111100111,d1
- beq.s .exit
- and.b #3,d1 ;but of same type ?
- bne.s .exit
- and.b #3,d0 ;which is invalid ?
- ;then equal
- .exit:
- rts
- ;ENDFOLD
- ;FOLD ReadIncrement
- ;*************************************************
- ;** ReadIncrement **
- ;** Provide the increment from one page **
- ;** descriptor to another in d0 **
- ;** get the page descriptor from the adt *a0 **
- ;** entry #d0 **
- ;** return that in *a0 **
- ;*************************************************
- ReadIncrement:
- btst #atdf_long,atd_NextType(a0)
- bne.s .long
- move.l atd_Pointer(a0),a0 ;get the pointer
- lea (a0,d0.w*4),a0
- moveq #4,d0
- rts
- .long:
- move.l atd_Pointer(a0),a0
- lea (a0,d0.w*8),a0
- moveq #8,d0
- rts
- ;ENDFOLD
-
-